package com.qiqi.ctbluetooth.util

import android.graphics.Color
import android.view.MotionEvent
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ToastUtils
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.components.YAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.highlight.Highlight
import com.github.mikephil.charting.listener.ChartTouchListener
import com.github.mikephil.charting.listener.OnChartGestureListener
import com.github.mikephil.charting.listener.OnChartValueSelectedListener
import com.qiqi.ctbluetooth.UserDataLocal
import com.qiqi.ctbluetooth.data.DacPointData
import kotlin.math.sqrt

object LineChartManager {
    const val RULER = "Ruler"
    const val WAVE_FROM = "Waveform"
    const val BAOLUO = "Baoluo"
    const val Default = "Default"
    const val DAC = "DAC"
    const val RULER_POINT = "RULE_POINT"
    const val WIDTH = 40
    const val MAX_X = 499
    const val MAX_Y = 254
    val GUIDE_X_1 = "X1"
    val GUIDE_X_2 = "X2"
    val GUIDE_X_3 = "X3"
    val GUIDE_X_4 = "X4"
    val GUIDE_X_5 = "X5"
    val GUIDE_X_START = "XSTART"
    val GUIDE_X_END = "XEND"
    val GUIDE_Y_1 = "Y1"
    val GUIDE_Y_2 = "Y2"
    val GUIDE_Y_3 = "Y3"
    val GUIDE_Y_4 = "Y4"
    val GUIDE_Y_5 = "Y5"
    val GUIDE_Y_START = "YSTART"
    val GUIDE_Y_END = "YEND"
    //测量尺的开始x坐标和结束x坐标
    var rule : Pair<Int, Int> = Pair(-1,-1)
    var ruleY = 0
    var dacList = mutableListOf<Entry>()


    fun initChart(lineChart: LineChart){
        lineChart.apply {
            setExtraOffsets(0f, 0f, 0f, 0f) // 确保没有额外的内边距
            minOffset = 0f // 确保最小偏移为0
            setNoDataText("无数据")
            //设置显示在图表右下角的描述文本。
            description.isEnabled = false

            setTouchEnabled(true)
            setDragEnabled(false)
            setScaleEnabled(false)
            setDrawGridBackground(false)
            setPinchZoom(false)
            isHighlightPerTapEnabled = false
            isHighlightPerDragEnabled = false


            legend.isEnabled = false

            extraTopOffset = 0f

            val xl: XAxis = xAxis
            xl.isEnabled = false

            // 图表左边的y坐标轴线
            val leftAxis: YAxis = axisLeft
            // 最小值
            leftAxis.mAxisMinimum = 0f
            leftAxis.mAxisMaximum = 254f
            //是否绘制坐标值
            leftAxis.setDrawLabels(false)
            leftAxis.setDrawGridLines(false)
            //是否绘制坐标线
            leftAxis.setDrawAxisLine(false)
            //是否绘制轴的网格线
            leftAxis.setDrawAxisLine(false)
            leftAxis.textColor = Color.RED
            leftAxis.isEnabled = true
            lineChart.notifyDataSetChanged()
            lineChart.invalidate()

            val rightAxis: YAxis = axisRight
            rightAxis.isEnabled = false


            onChartGestureListener = object : OnChartGestureListener{
                override fun onChartGestureStart(me: MotionEvent?, lastPerformedGesture: ChartTouchListener.ChartGesture?) {

                }

                override fun onChartGestureEnd(me: MotionEvent?, lastPerformedGesture: ChartTouchListener.ChartGesture?) {

                }

                override fun onChartLongPressed(me: MotionEvent?) {

                }

                override fun onChartDoubleTapped(me: MotionEvent?) {

                }

                override fun onChartSingleTapped(me: MotionEvent?) {
                    var touchX = me?.x ?: 0f
                    var touchY = me?.y ?: 0f
//                    LogUtils.d("touch===> touchX:$touchX,touchY:$touchY")

                    var point = lineChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(touchX, touchY)
                    var xValue = point.x.toFloat()
                    var yValue = point.y.toFloat()
//                    LogUtils.d("point====> xValue:$xValue,yValue:$yValue")

                    var formattedX = lineChart.xAxis.getValueFormatter().getFormattedValue(xValue);
                    var formattedY = lineChart.axisLeft.getValueFormatter().getFormattedValue(yValue, lineChart.axisLeft);

//                    LogUtils.d("formatted====> formattedX:$formattedX,formattedY:$formattedY")

                    addRuler(lineChart, entry = Entry(formattedX.toFloat(), formattedY.toFloat()))
                }

                override fun onChartFling(me1: MotionEvent?, me2: MotionEvent?,velocityX: Float, velocityY: Float) {

                }

                override fun onChartScale(me: MotionEvent?, scaleX: Float, scaleY: Float) {
                }

                override fun onChartTranslate(me: MotionEvent?, dX: Float, dY: Float) {

                }

            }


            // 绘制一条默认的线，此处为了解决y轴最右侧辅助线无法出现的问题
            val entries = mutableListOf<Entry>()
            for (i in 0..499) {
                entries.add(Entry(i.toFloat(), 0f))
            }

            // 如果没有现有数据，创建一个新的LineData对象
            var dataSet = LineDataSet(entries, Default).apply {
                color = Color.TRANSPARENT
                lineWidth = 1f
                setDrawCircles(false)  // 关闭数据点的绘制
                setDrawValues(false)   // 关闭数据值的显示
            }

            var lineData = LineData(dataSet)
            lineChart.data = lineData
            lineChart.invalidate()
        }
    }

    /**
     * 添加测量尺
     * */
    fun addRuler(lineChart: LineChart, entry: Entry?) {
        if (entry == null){
            return
        }
        //开始显示的X坐标
        var startX = when {
            entry.x - WIDTH / 2 < 0 -> 0f
            entry.x + WIDTH / 2 > MAX_X -> (MAX_X -WIDTH).toFloat()
            else -> entry.x - WIDTH / 2
        }
        //更新测量尺的的X轴开始坐标和结束坐标
        rule = Pair(startX.toInt(), (startX + WIDTH).toInt())
        ruleY = entry.y.toInt()
        var entries = mutableListOf<Entry>()

        for (i in rule.first until rule.second) {
            entries.add(Entry(i.toFloat(), entry.y))
//            entries.add(Entry(i.toFloat(), 127F))
        }
        // 获取现有的LineData
        val existingLineData = lineChart.data
        var rulerSet = existingLineData.getDataSetByLabel(RULER,true)
        //如果测量尺存在，刷新测量尺,不存在则去创建
        if (rulerSet != null){
            rulerSet = rulerSet as LineDataSet
            rulerSet.values = entries
            rulerSet.notifyDataSetChanged()
        }else{
            val newRulerSet = LineDataSet(entries, RULER).apply {
                color = Utils.getFanValue(UserDataLocal.rulerBg)
                lineWidth = 3f
                setDrawCircles(false)  // 关闭数据点的绘制
                setDrawValues(false)   // 关闭数据值的显示
            }
            existingLineData.addDataSet(newRulerSet)
        }
        // 通知图表更新
        lineChart.invalidate()
    }

    fun  getDacLine(lineChart: LineChart) : List<Entry>{
        // 获取现有的LineData
        val existingLineData = lineChart.data
        var dacSet = existingLineData.getDataSetByLabel(DAC,true)
        if (dacSet != null){
            dacSet = dacSet as LineDataSet
            return dacSet.values
        }
        return emptyList<Entry>()
    }


    fun updateDacLine(lineChart: LineChart,pointList: MutableList<DacPointData>){

        LogUtils.e("DAC","dacPointList====>${pointList.size}")
        //根据x的值从小到大排序
        pointList.sortBy { it.x }
        var entries = mutableListOf<Entry>()
        LogUtils.e("DAC原始",pointList.toString())
        for (item in pointList){
            entries.add(Entry(item.x, item.y))
        }

        if (entries.isNotEmpty()){
            //判断entries 第一项的x值是否为0，如果为0则删除
            if (entries[0].x == 0f){
                entries.removeAt(0)
            }
            //不为0则在list添加第一条数据，entries第一项的x为0，y为列表第一项的y值
            entries.add(0, Entry(0f, pointList[0].y))
            //判断当前x轴是否是499，如果小于499，获取entries 最后一项数据的x数据，循环添加数据至499
            //平滑计算后续点的位置
            if (entries[entries.size - 1].x < MAX_X){
                for (i in entries[entries.size - 1].x.toInt() until MAX_X){
                    var y = entries.last().y * sqrt(Math.pow(i.toDouble() / (i + 1),3.0))
                    entries.add(Entry(entries.last().x +1 , y.toFloat()))
                }
            }
        }
        //dad 数据处理
        dacList = mutableListOf()
        dacList = entries.toMutableList()

        //获取修正之后的数据
        var newDacList =  addFixesPoint(entries)
//        var newDacList =  entries

        LogUtils.e("DAC",newDacList.toString())

        // 获取现有的LineData
        val existingLineData = lineChart.data
        var adcSet = existingLineData.getDataSetByLabel(DAC,true)
        //如果dac存在，刷新dac,不存在则去创建
        if (adcSet != null && newDacList.isNotEmpty()){
            LogUtils.e("DAC","刷新dac")
            adcSet = adcSet as LineDataSet
            adcSet.values = newDacList
            adcSet.notifyDataSetChanged()
            lineChart.invalidate()
        }else if(adcSet != null && newDacList.isEmpty()){
            //删除数组
            LogUtils.e("DAC","删除dac")
            existingLineData.removeDataSet(adcSet)
            lineChart.invalidate()
        }else if (adcSet == null && newDacList.isNotEmpty()){
            //创建数组
            LogUtils.e("DAC","创建dac")
            var creatSet = LineDataSet(newDacList, DAC).apply {
                color =  if( UserDataLocal.isOpenDAC) UserDataLocal.dacBg else Color.TRANSPARENT
                lineWidth = 1f
                setDrawCircles(false)  // 关闭数据点的绘制
                setDrawValues(false)   // 关闭数据值的显示
            }
            existingLineData.addDataSet(creatSet)
            lineChart.invalidate()
        }

    }

    /**
     * 添加修正曲线
     * */
    fun addFixesPoint(list: MutableList<Entry>) : MutableList<Entry>{
        var newList = mutableListOf<Entry>()
        var i = 0
        var y = 1
        while (y < list.size) {
            // 每循环一次加入一个数据
            newList.add(Entry(list[i].x, if(list[i].y > 254) 254f else list[i].y))
            // 判断前一个大于254而下一个小于254出现问题的线段
            if (list[i].y > 254 && list[y].y < 254){
                // 计算出差值来给中间的空白打上点
                val count = (list[y].x - list[i].x).toInt()
                val xie = (list[i].y - list[y].y) / count
                // 开始修正此段数据
                for (x in 1 until count) {
                    // 新点 key为x value为y
                    val newPoint = Entry(list[i].x + x, list[i].y - x * xie)
                    // 判断如果y>254那么就等于254小于直接赋值
                    if (newPoint.y > 254) {
                        newPoint.y = 254f
                    }
                    newList.add(newPoint) // 添加数据
                }
            }
            i++
            y++
        }
        return newList
    }

    fun updateDataColor(lineChart: LineChart,name:String, color: Int){
        val existingLineData = lineChart.data
        if (existingLineData != null){
            var dataSet = existingLineData.getDataSetByLabel(name,true)
            if (dataSet != null){
                dataSet = dataSet as LineDataSet
                dataSet.color = color
                dataSet.notifyDataSetChanged()
                // 通知图表更新
                lineChart.invalidate()
            }
        }

    }

    fun addBaoluo(lineChart: LineChart, entries: MutableList<Entry>){
        // 获取现有的LineData
        val existingLineData = lineChart.data
        if (existingLineData != null){
            var dataSet = existingLineData.getDataSetByLabel(BAOLUO,true)
            if (dataSet != null && entries.isNotEmpty()){
               //更新数组
                dataSet = dataSet as LineDataSet
                dataSet.values = entries
                dataSet.notifyDataSetChanged()
                lineChart.invalidate()
            }else if (dataSet != null && entries.isEmpty()){
                //删除数组
                existingLineData.removeDataSet(dataSet)
                lineChart.invalidate()
            }else if (dataSet == null && entries.isNotEmpty()){
                //创建数组
                var creatSet = LineDataSet(entries, BAOLUO).apply {
                    color = Utils.getFanValue(UserDataLocal.baoluoBg)
                    lineWidth = 1f
                    setDrawCircles(false)  // 关闭数据点的绘制
                    setDrawValues(false)   // 关闭数据值的显示
                }
                existingLineData.addDataSet(creatSet)
                lineChart.invalidate()
            }
        }
    }

    fun addRulePoint(lineChart: LineChart, entries: MutableList<Entry>){
//       LogUtils.e("测量点",entries.toString())
        // 获取现有的LineData
        val existingLineData = lineChart.data
        if (existingLineData != null){
            var dataSet = existingLineData.getDataSetByLabel(RULER_POINT,true)
            if (dataSet != null && entries.isNotEmpty()){
                //更新数组
                dataSet = dataSet as LineDataSet
                dataSet.values = entries
                dataSet.notifyDataSetChanged()
                lineChart.invalidate()
            }else if (dataSet != null && entries.isEmpty()){
                //删除数组
                existingLineData.removeDataSet(dataSet)
                lineChart.invalidate()
            }else if (dataSet == null && entries.isNotEmpty()){
                //创建数组
                var creatSet = LineDataSet(entries, RULER_POINT).apply {
                    color = UserDataLocal.rulePoint
                    lineWidth = 1f
                    setDrawCircles(false)  // 关闭数据点的绘制
                    setDrawValues(false)   // 关闭数据值的显示
                }
                existingLineData.addDataSet(creatSet)
                lineChart.invalidate()
            }
        }
    }

    fun addWaveform(lineChart: LineChart, entries: MutableList<Entry>){
        // 获取现有的LineData
        val existingLineData = lineChart.data
        // 检查是否存在数据
        if (existingLineData != null &&  existingLineData.dataSetCount > 0) {
            var waveformSet = existingLineData.getDataSetByLabel(WAVE_FROM,true)
            if (waveformSet != null){
                waveformSet = waveformSet as LineDataSet
                waveformSet.values = entries
                waveformSet.notifyDataSetChanged()
                lineChart.invalidate()
            }else{
                val newWaveformSet = LineDataSet(entries, WAVE_FROM).apply {
                    color = Utils.getFanValue(UserDataLocal.waveformBg)
                    lineWidth = 1f
                    setDrawCircles(false)  // 关闭数据点的绘制
                    setDrawValues(false)   // 关闭数据值的显示
                }
                existingLineData.addDataSet(newWaveformSet)
                lineChart.invalidate()
            }
        } else {
            // 如果没有现有数据，创建一个新的LineData对象
            var dataSet = LineDataSet(entries, WAVE_FROM).apply {
                color = Utils.getFanValue(UserDataLocal.waveformBg)
                lineWidth = 1f
                setDrawCircles(false)  // 关闭数据点的绘制
                setDrawValues(false)   // 关闭数据值的显示
            }

            var lineData = LineData(dataSet)
            lineChart.data = lineData
            lineChart.invalidate()
        }

    }


    fun setGuidelines(lineChart: LineChart){
        val X_LENGTH = 500
        val Y_LENGTH = 254

        var y1Entries = mutableListOf<Entry>()
        var y2Entries = mutableListOf<Entry>()
        var y3Entries = mutableListOf<Entry>()
        var y4Entries = mutableListOf<Entry>()
        var y5Entries = mutableListOf<Entry>()
        var yStartEntries = mutableListOf<Entry>()
        var yEndEntries = mutableListOf<Entry>()
        //Y1 Y2 Y4 Y5一共循环50次，间距为 254/50，一共添加50次   Y3一共添加25次，一共添加25次



        //每次加5.1，而不是5， 一共循环50次怎么写循环

        for (i in 1..50) {
            var value = (i* 5.1).toFloat()
            y1Entries.add(Entry((X_LENGTH*0.2).toFloat(), value))
            y2Entries.add(Entry((X_LENGTH*0.4).toFloat(), value))
            if (i % 2 == 0){
                y3Entries.add(Entry((X_LENGTH*0.5).toFloat(), value))
            }
            y4Entries.add(Entry((X_LENGTH*0.6).toFloat(), value))
            y5Entries.add(Entry((X_LENGTH*0.8).toFloat(), value))
            yStartEntries.add(Entry(0f, value))
            yEndEntries.add(Entry(498.5f, value))
        }

        setGuideLineSet(lineChart, y1Entries, GUIDE_Y_1)
        setGuideLineSet(lineChart, y2Entries, GUIDE_Y_2)
        setGuideLineSet(lineChart, y3Entries, GUIDE_Y_3)
        setGuideLineSet(lineChart, y4Entries, GUIDE_Y_4)
        setGuideLineSet(lineChart, y5Entries, GUIDE_Y_5)
        setGuideLineSet(lineChart, yStartEntries, GUIDE_Y_START)
        setGuideLineSet(lineChart, yEndEntries, GUIDE_Y_END)

        var x1Entries = mutableListOf<Entry>()
        var x2Entries = mutableListOf<Entry>()
        var x3Entries = mutableListOf<Entry>()
        var x4Entries = mutableListOf<Entry>()
        var x5Entries = mutableListOf<Entry>()
        var xStartEntries = mutableListOf<Entry>()
        var xEndEntries = mutableListOf<Entry>()

        for (i in 0 until X_LENGTH step 10) {
            x1Entries.add(Entry(i.toFloat(),(Y_LENGTH*0.2).toFloat()))
            x2Entries.add(Entry(i.toFloat(),(Y_LENGTH*0.4).toFloat()))
            //这个为20位添加一次
            if (i % 20 == 0){
                x3Entries.add(Entry(i.toFloat(),(Y_LENGTH*0.5).toFloat()))
            }
            x4Entries.add(Entry(i.toFloat(),(Y_LENGTH*0.6).toFloat()))
            x5Entries.add(Entry(i.toFloat(),(Y_LENGTH*0.8).toFloat()))
            xStartEntries.add(Entry(i.toFloat(),0F))
            xEndEntries.add(Entry(i.toFloat(),255F))
        }

        setGuideLineSet(lineChart, x1Entries, GUIDE_X_1)
        setGuideLineSet(lineChart, x2Entries, GUIDE_X_2)
        setGuideLineSet(lineChart, x3Entries, GUIDE_X_3)
        setGuideLineSet(lineChart, x4Entries, GUIDE_X_4)
        setGuideLineSet(lineChart, x5Entries, GUIDE_X_5)
        setGuideLineSet(lineChart, xStartEntries, GUIDE_X_START)
        setGuideLineSet(lineChart, xEndEntries, GUIDE_X_END)
    }

    fun updateGuideLineAllColor(lineChart: LineChart){
        val guideLines = listOf(
            GUIDE_X_1, GUIDE_X_2, GUIDE_X_3, GUIDE_X_4, GUIDE_X_5,
            GUIDE_Y_1, GUIDE_Y_2, GUIDE_Y_3, GUIDE_Y_4, GUIDE_Y_5
        )
        for (guideLine in guideLines) {
            updateGuideLineColor(lineChart, guideLine)
        }
    }

    private fun updateGuideLineColor(lineChart: LineChart,name:String){
        val existingLineData = lineChart.data
        if (existingLineData != null){
            var dataSet = existingLineData.getDataSetByLabel(name,true)
            if (dataSet != null){
                ToastUtils.showShort(if (UserDataLocal.colorBg == Color.BLACK) "黑色" else "白色")
                dataSet = dataSet as LineDataSet
                dataSet.apply{
                    color = if (UserDataLocal.colorBg == Color.BLACK) Color.BLACK else Color.WHITE
                    setCircleColor(Color.RED)
                    lineWidth = 0f
                    circleRadius = 0.5f  // 设置圆点半径
//                    setCircleColor(if (UserDataLocal.colorBg == Color.BLACK) Color.WHITE else Color.BLACK)
                    notifyDataSetChanged()
                }
                // 通知图表更新
                lineChart.invalidate()
            }
        }
    }


    fun setGuideLineSet(lineChart: LineChart, entries: MutableList<Entry>, name: String){
        // 获取现有的LineData
        val existingLineData = lineChart.data
        if (existingLineData != null){
            var dataSet = existingLineData.getDataSetByLabel(name,true)
            if (dataSet != null && entries.isNotEmpty()){
                //更新数组
                existingLineData.removeDataSet(dataSet)
                var creatSet = LineDataSet(entries, name).apply {
                    color = if (UserDataLocal.colorBg == Color.BLACK) Color.BLACK else Color.WHITE
                    lineWidth = 0f
                    circleRadius = 1f  // 设置圆点半径
                    setCircleColor(if (UserDataLocal.colorBg == Color.BLACK) Color.WHITE else Color.BLACK)
                    setDrawCircles(true)  // 关闭数据点的绘制
                    setDrawValues(false)   // 关闭数据值的显示
                    setDrawHighlightIndicators(false)
                }
                existingLineData.addDataSet(creatSet)
                lineChart.invalidate()
            }else if (dataSet != null && entries.isEmpty()){
                //删除数组
                existingLineData.removeDataSet(dataSet)
                lineChart.invalidate()
            }else if (dataSet == null && entries.isNotEmpty()){
                //创建数组
                var creatSet = LineDataSet(entries, name).apply {
                    color = if (UserDataLocal.colorBg == Color.BLACK) Color.BLACK else Color.WHITE
                    lineWidth = 0f
                    circleRadius = 1f  // 设置圆点半径
                    setCircleColor(if (UserDataLocal.colorBg == Color.BLACK) Color.WHITE else Color.BLACK)
                    setDrawCircles(true)  // 关闭数据点的绘制
                    setDrawValues(false)   // 关闭数据值的显示
                    setDrawHighlightIndicators(false)
                }
                existingLineData.addDataSet(creatSet)
                lineChart.invalidate()
            }
        }else{
            var creatSet = LineDataSet(entries, name).apply {
                color = if (UserDataLocal.colorBg == Color.BLACK) Color.BLACK else Color.WHITE
                lineWidth = 0f
                circleRadius = 1f  // 设置圆点半径
                setCircleColor(if (UserDataLocal.colorBg == Color.BLACK) Color.WHITE else Color.BLACK)
                setDrawCircles(true)  // 关闭数据点的绘制
                setDrawValues(false)   // 关闭数据值的显示
                setDrawHighlightIndicators(false)
            }
            var lineData = LineData(creatSet)
            lineChart.data = lineData
            lineChart.invalidate()
        }



    }
}